#!/usr/sbin/python
# -*- coding: utf-8 -*-
'''
Created on 2010-10-30
## Copyright (C) 2007-2010 The PowerallNetworks
## See LICENSE for details
##----------------------------------------------------------------------
This program is to generate the report from the raw networks data.
'''
import os
import re
import copy
import ftplib
import StringIO

FTPURL=""
FTPUSER=""
FTPPASSWORD=""

TMPFOLDER=""

netdata={}

class NetRouteAnalyze:
    '''
    analyze the raw data, and set the route 
    '''
    def __init__(self,config):
        '''
        @param config:{
            "ftp_host":"",
            "ftp_port":"",
            "ftp_user":"",
            "ftp_password":"",
            "ftp_folder":"",
            "localdata_folder":"",
            "tmp_folder":"",
            "debug":False
        }
        '''
        self.config = copy.deepcopy(config)
        if "ftp_user" in config and config["ftp_user"] != "":
            self.url_prefix = "ftp://%(ftp_user)s:%(ftp_password)s@%(ftp_host)s:%(ftp_port)s" % self.config
            if config["ftp_folder"]:
                self.url_prefix += "/" + config["ftp_folder"]
                
        self.localdata_folder = config["localdata_folder"]
        self.tmp_folder = config["tmp_folder"]
        self.debug = config["debug"]
        
    def initEnv(self,config):
        '''
        download the raw data to local
        '''
        
    def analyze(self):
        '''
        read and analyze the raw data and sort in to structured object 
        '''
        self.netdata = {}
        for root,mydirs,myfiles in os.walk(self.localdata_folder):
            for myfile in myfiles:
                if len(myfile)<4 or myfile[-4:]!= ".txt":
                    continue
                items = myfile[:-4].split("__")
                # simple checking
                if  len(items) != 4 or \
                    not items[2].upper() in ["PING","TRACE"] or \
                    len(items[3]) != 14:
                        if self.debug:
                            print "file name [%s] format wrong, should be [source__target__action__time.txt]" % (myfile)
                            print "action should be ping|trace" 
                        continue
                 
                # parse name
                item_name = items[0] + "__" + items[1]
                if not item_name in self.netdata.keys():
                    item_info = self.netdata[item_name] = {}
                    item_info["source_host"] = items[0].replace("_", ".")
                    item_info["target_host"] = items[1].replace("_", ".")
                    item_info["key"] = items[0]+"__"+items[1]
                    item_info["net_data"] = {}
                else:
                    item_info = self.netdata[item_name]
                
                if not items[3] in item_info["net_data"]:
                    net_data = item_info["net_data"][items[3]] = {
                        "time_stamp":items[3][:8]+" "+items[3][8:12],
                        "ping_data_link":"#",
                        "trace_data_link":"#",
                        "ping_loss":"-"
                        }
                else:
                    net_data = item_info["net_data"][items[3]]
                    
                if items[2].upper() == "PING":
                    net_data["ping_data_link"] = self.url_prefix + "/" + myfile
                    # parse file:
                    try:
                        f = open(os.path.join(root,myfile),"r")
                        content = f.read()
                        
                        net_data["ping_loss"] = re.findall("\d+%", content)[-1]
                        f.close()
                    except Exception,e:
                        if self.debug:
                            print str(e)
                else:
                    net_data["trace_data_link"] = self.url_prefix + "/" + myfile
    
    def generateIndex(self,filter):
        '''
        Only generate the IP networks status in the filter list 
        @param filter:[IP,IP]
        '''
        ip_index = {}
        for ip in filter:
            ip_index[ip] = {
                "to":[],
                "from":[]
            }
            
        for k,v in self.netdata.iteritems():
            if v["source_host"] in ip_index:
                ip_index[v["source_host"]]["to"].insert(-1, {"target_host":v["target_host"],"key":k})
            elif v["target_host"] in ip_index:
                ip_index[v["target_host"]]["from"].insert(-1, {"source_host":v["source_host"],"key":k})
            else:
                continue
        
        self.ip_index = ip_index        
                
    def generateHtml(self):
        '''
        generate the html file from the structured object
        '''
        if self.ip_index:
            index_html = '''<table class="host_index">'''
            for k,v in self.ip_index.iteritems():
                index_html += '''<tr><td>'''+k+'''</td><td>To</td><td>'''
                for target in v["to"]:
                    index_html += '''<a href="#%(key)s">%(target_host)s</a> | ''' % target
                index_html += "</td></tr>"
                index_html += '''<tr><td>'''+k+'''</td><td>From</td><td>'''
                for target in v["from"]:
                    index_html += '''<a href="#%(key)s">%(source_host)s</a> | ''' % target
                index_html += "</td></tr>"
            index_html += "</table>"
        else:
            index_html = ""
                
        html = '''
        <html>
        <head>
        <style type="text/css">
        table
        { font-family: Verdana;
        font-weight: normal;
        font-size: 11px;
        color: #404040;
        background-color: #fafafa;
        border: 1px #6699CC solid;
        border-collapse: collapse;
        border-spacing: 0px;
        margin-top: 0px;}
        
        table.host_list{
        width: 500px;
        }
        table.host_index{
        width: 100%;
        }
        table.data_list{
        width: 300px;
        }
        table.header{
        width: 100%;
        }
        
        table td.servHd
        { border-bottom: 2px solid #6699CC;
        background-color: #BEC8D1;
        text-align: center;
        font-family: Verdana;
        font-weight: bold;
        font-size: 11px;
        color: #404040;}
        
        
        table td
        { border-bottom: 1px dotted #6699CC;
        font-family: Verdana, sans-serif, Arial;
        font-weight: normal;
        font-size: 11px;
        color: #404040;
        background-color: white;
        text-align: left;
        padding-left: 3px;}

        </style>

        </head>
        <body>
        <h3>Index</h3>
        '''+index_html+'''
        <h3>Networks Data</h3>        
        <table class='header'>
            <tr><td> <div style="height:400px;overflow-x:auto; overflow-y:auto; ">
        <table class='host_list'>
        '''
        
        for k,v in self.netdata.iteritems():
            html += '''<tr>
                <td class="servHd"><a name="%(key)s">%(source_host)s To %(target_host)s</a></td>
                <td>
                ''' % v
            html += '''<table class='data_list'>''' 
            vvv = v["net_data"].values()
            vvv.sort( key=lambda obj:obj.get("time_stamp"), reverse=False)
            for vv in vvv:
                html += '''
                        <tr>
                            <td>%(time_stamp)s<td>
                            <td>
                                <a target="raw_data" href="%(ping_data_link)s">ping lost: %(ping_loss)s</a>
                                <a target="raw_data" href="%(trace_data_link)s">trace</a>
                            </td>
                        </tr>
                ''' % vv 
            html += '''</table>
                </td>
            </tr>'''
        html += '''
            </table>
            </div>
            </td>
                <td><iframe name="raw_data" height="400px" width="600px"></iframe></td>
            </tr>
        </table>
        <p> 
        The project allocated on <a href="http://code.google.com/p/network-state-monitor/source/checkout" >here</a>, This page is the result of the report. 
        </p>
            </body>
            </html>'''
            
        self.uploadFile(html)
    def uploadFile(self,html):
        '''
        
        '''
        try:
            self.cobj = ftplib.FTP()
            if self.debug :
                self.cobj.set_debuglevel(2)
                
            self.cobj.connect(self.config["ftp_host"],self.config["ftp_port"])
            self.cobj.login(self.config["ftp_user"],self.config["ftp_password"])
            if self.config["ftp_folder"]:
                self.cobj.cwd(self.config["ftp_folder"])
            
            file_handler = StringIO.StringIO(html)
            self.cobj.storbinary('STOR '+"report.html",file_handler)
            file_handler.close()

            return True
        except Exception,ftperr:
            if self.debug:
                print "upload error"+str(ftperr)
            return False


if __name__ == '__main__':
    def usage():
        print "This program is part of the network status simple-analyze project"
        print "This program is to analyze the data and create the report of ping and trace."
        print "you should mirror the raw data from the FTP server first"
    
    default_config = {
            "ftp_host":"ftp.cloudwww-demo1.com",
            "ftp_port":"21",
            "ftp_user":"hntest",
            "ftp_password":"forhntest",
            "ftp_folder":"",
            "localdata_folder":"F:\\Raymond Space\\support\\netdata\\",
            "tmp_folder":"",
            "debug":True
        }
    work = NetRouteAnalyze(default_config)
    work.analyze()
    work.generateIndex(["203.169.242.34","218.213.194.82"])
    work.generateHtml()
    
    